<?php
/**
 * @see Zend_Rest_Client
 */
require_once 'Zend/Rest/Client.php';

/**
 * @see Zend_Rest_Client_Result
 */
require_once 'Zend/Rest/Client/Result.php';

class Bemigo_Service_Hunch extends Zend_Rest_Client{

	const API_BASE_URI = 'http://api.hunch.com';

	protected $_localHttpClient = null;

	protected $_methodType;

	protected $_options = array();

	protected $_methodTypes = array(
        'get-recommendations',
        'get-results',
        'get-similar-results',
        'get-topics',
        'get-result-topics'
    );

	public function __construct($options = null){

		$this->setUri(self::API_BASE_URI);

        if ($options instanceof Zend_Config) {
            $options = $options->toArray();
        }

        if (!is_array($options)) {
            $options = array();
        }
        $options['siteUrl'] = self::API_BASE_URI;

        $this->_options = $options;

        $this->setLocalHttpClient(clone self::getHttpClient());
	}

    /**
     * Set local HTTP client as distinct from the static HTTP client
     * as inherited from Zend_Rest_Client.
     *
     * @param Zend_Http_Client $client
     * @return self
     */
    public function setLocalHttpClient(Zend_Http_Client $client)
    {
        $this->_localHttpClient = $client;
        $this->_localHttpClient->setHeaders('Accept-Charset', 'ISO-8859-1,utf-8');
        return $this;
    }

    /**
     * Get the local HTTP client as distinct from the static HTTP client
     * inherited from Zend_Rest_Client
     *
     * @return Zend_Http_Client
     */
    public function getLocalHttpClient()
    {
        return $this->_localHttpClient;
    }

    /**
     * Performs an HTTP GET request to the $path.
     *
     * @param string $path
     * @param array  $query Array of GET parameters
     * @throws Zend_Http_Client_Exception
     * @return Zend_Http_Response
     */
    protected function _get($path, array $query = null)
    {
        $this->_prepare($path);
        $this->_localHttpClient->setParameterGet($query);
        return $this->_localHttpClient->request(Zend_Http_Client::GET);
    }

    /**
     * Performs an HTTP POST request to $path.
     *
     * @param string $path
     * @param mixed $data Raw data to send
     * @throws Zend_Http_Client_Exception
     * @return Zend_Http_Response
     */
    protected function _post($path, $data = null)
    {
        $this->_prepare($path);
        return $this->_performPost(Zend_Http_Client::POST, $data);
    }

    /**
     * Perform a POST or PUT
     *
     * Performs a POST or PUT request. Any data provided is set in the HTTP
     * client. String data is pushed in as raw POST data; array or object data
     * is pushed in as POST parameters.
     *
     * @param mixed $method
     * @param mixed $data
     * @return Zend_Http_Response
     */
    protected function _performPost($method, $data = null)
    {
    	$client = $this->_localHttpClient;
    	$auth_sig = $this->_signRequest($data);
        if (is_string($data)) {
            $client->setRawData($data."&auth_sig=".$auth_sig);
        } elseif (is_array($data) || is_object($data)) {
        	$data = array_merge($data, array("auth_sig"=>$auth_sig));
            $client->setParameterPost((array) $data);
        }
        return $client->request($method);
    }

    protected function _signRequest($params){
    	// Sort the array by key
	    ksort($params);

	    // Build the canonical query string
	    $canonical = '';
	    foreach ($params as $key => $val) {
	        $canonical .= "$key=".$this->enc(utf8_encode($val))."&";
	    }

	    // Remove the trailing ampersand
	    $canonical = preg_replace("/&$/", '', $canonical);

	    // Build the sign
	    $string_to_sign = $this->enc($canonical) . $this->_options["secret"];

	    //print $string_to_sign . "<BR>";

	    // Calculate our actual signature and base64 encode it
	    $signature = bin2hex(hash('sha1', $string_to_sign, $this->_options["secret"]));

	    return rawurlencode($signature);
    }

    protected function enc($c) {
	    $c = str_replace(array('+', '/', '@', '%20'), array('%2B', '%2F', '%40', '+'), $c);
	    return $c;

	}

    /**
     * Call a remote REST web service URI and return the Zend_Http_Response object
     *
     * @param  string $path            The path to append to the URI
     * @throws Zend_Rest_Client_Exception
     * @return void
     */
    protected function _prepare($path)
    {
        // Get the URI object and configure it
        if (!$this->_uri instanceof Zend_Uri_Http) {
            require_once 'Zend/Rest/Client/Exception.php';
            throw new Zend_Rest_Client_Exception(
                'URI object must be set before performing call'
            );
        }

        $uri = $this->_uri->getUri();

        if ($path[0] != '/' && $uri[strlen($uri) - 1] != '/') {
            $path = '/' . $path;
        }

        $this->_uri->setPath($path);
        /**
         * Get the HTTP client and configure it for the endpoint URI.
         * Do this each time because the Zend_Http_Client instance is shared
         * among all Zend_Service_Abstract subclasses.
         */
        $this->_localHttpClient->resetParameters()->setUri((string) $this->_uri);
    }

    public function getResults(array $params = array()){
    	$path = '/api/v1/get-results';
    	$response = $this->_post($path, $params);
    	return json_decode($response->getBody());
    }

    public function getSimilarResults(array $params = array()){
    	$path = '/api/v1/get-similar-results';
    	$response = $this->_post($path, $params);
    	return json_decode($response->getBody());
    }

}